Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix culling with infinite projection matrix #95944

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Flarkk
Copy link

@Flarkk Flarkk commented Aug 22, 2024

Closes godotengine/godot-proposals#10515.

Fixes #55070

I came to a slightly different implementation than the one I originally thought about in the proposal.

When far value outpasses the numerical precision required to have the addition and substraction with near making any difference, the perspective matrix becomes an infinite projection matrix.

When this happens, the -(far + near) / (far - near) component of the perspective matrix returns -1 which makes the normal calculation yield a zero vector, and breaks further steps down.

With this PR, when the far plane normal extraction gives 0, the normal is instead set to Vector3(0, 0, -1), and the intercept set to INFINITY.

Test project : PR95944.zip

Camera has near = 0.05 and far ~= 1e20, perspective projection.
Pink sphere is at z ~= -1e20
Blue sphere is at z = -1e15
Green sphere is at z = -1e10
Orange sphere is at z = -1e5
Black sphere is at z = -1

Without this PR :

image

With this PR :

image

@Flarkk Flarkk requested review from a team as code owners August 22, 2024 11:33
@AThousandShips AThousandShips added this to the 4.x milestone Aug 22, 2024
@Flarkk Flarkk force-pushed the infinite_projection branch 2 times, most recently from 5d27f77 to 3287465 Compare August 22, 2024 12:38
@tetrapod00
Copy link
Contributor

Does this introduce another change in behavior when working with clip space in shaders like reverse-z did, like e.g. reconstructing position from depth? Or does the math work out such that shaders are unchanged? I don't see any GLSL in the changed files.

Copy link
Author

@Flarkk Flarkk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there is no impact on shaders.
In fact, the only thing this PR changes is how the frustum planes (and specifically the far plane) are extracted from the projection matrix. The matrix itself is passed through unchanged as before to the rest of the pipeline, including the GPU parts.
Frustum planes are extracted and used in a handful of culling operations, on the CPU, mainly geometry culling and light culling.
You can find them back by searching calls to Projection::get_projection_planes() throughout the code.
This is really the only function affected by the PR, speaking of the core computational logic.

@Flarkk
Copy link
Author

Flarkk commented Aug 23, 2024

Stumbled upon a few other places in Projection that need the fix on z plane calculation (other than Projection::get_projection_planes()).

Some of those functions are not used anywhere in the code but could still be called in user modules or custom builds :

  • Projection::get_projection_plane()
  • Projection::get_z_far()
  • Projection::get_far_plane_half_extents()

I just updated the PR.

@AThousandShips AThousandShips removed request for a team August 23, 2024 17:44
@Flarkk Flarkk changed the title Add support for infinite projection matrix Add support for culling with infinite projection matrix Aug 24, 2024
@Flarkk Flarkk changed the title Add support for culling with infinite projection matrix Fix culling with infinite projection matrix Aug 24, 2024
@Flarkk
Copy link
Author

Flarkk commented Sep 12, 2024

Notes from the rendering weekly meeting :

is it fine to “detect” infinite matrices from their values right into Projection, instead of passing through a flag set by Camera3D based on far value ? (I’ve seen a “is_orthogonal” flag passed through whereas orthogonality could have been likewise detected from the matrix components themselves)

Yes, detecting infinite far is fine, but the fact that the projection uses an infinite far should propagate to further steps in rendering (i.e. the construction of the projection matrix + projection for screen space effects)

any further test project needed to bullet proof the fix ? (thinking of light culling, fog rendering, gi, and other stuff that uses far plane extraction)

Extensive testing will be needed. I don't think we have test coverage over this yet. So probably need to write code tests as well as a graphical demo for comparison

any other changes you may have in mind to fully unlock infinite far planes ? (thinking of 1 minor improvement : remove far distance capping in editor - but there might be more)

This is a good start, but the support would need to reach through the rendering pipeline to anything that is touched by the far plane. We rely on the far distance in many places in the renderer, all of these need to be checked

@roalyr
Copy link

roalyr commented Sep 20, 2024

I am sorry, I can not help with tests on this one after all. Too much work and life issues now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants